<template>
    <view class="bar c-flex_row c-align_center">
        <view class="progress item c-flex_1 c-flex_row c-align_center c-position_relative">
            <progress class="body" :percent='audioPercent' :border-radius='4' :stroke-width='8' activeColor='#ffda17'
                backgroundColor='#e9e9e9'></progress>
            <movable-area class="control-box c-position_absolute">
                <movable-view class='control-button c-position_relative' direction="horizontal" :x='controlX'
                    @change='controlChange'>
                    <view class="control-bg c-position_absolute"></view>
                </movable-view>
            </movable-area>
        </view>
        <view class="time item">
            {{timeValue}}
        </view>
        <view class="button item play" @click="tapPlay">
            <uni-icons v-if='play' custom-prefix="iconfont" type="icon-e-24gf-pause2" color="#333"
                size="24"></uni-icons>
            <uni-icons v-else custom-prefix="iconfont" type='icon-e-sanjiaoxing' color="#333" size="24"></uni-icons>
        </view>
        <view class="button item speed" @click="tapRate">
            <view class="title">
                {{playRateValue}}
            </view>
        </view>
        <view class="button item pdf" @click="tapPDF" v-if='ableDownloadPDF'>
            <uni-icons custom-prefix="iconfont" type="icon-e-pdf" color="#333" size="24"></uni-icons>
        </view>
    </view>
</template>

<script>
    export default {
        props: {
            src: {
                type: String,
                default: null
            },
            ableDownloadPDF: {
                type: Boolean,
                default: false
            }
        },
        data: function() {
            return {
                processWidth: 0,
                audioContext: null,
                totalTime: 0,
                currentTime: 0,
                playRate: 1.0,
                controlX: 0,
                play: false
            }
        },
        watch: {
            src: function(n) {
                if (n) {
                    this.createAudioContext(n);
                } else {
                    this.destroyedAudioContext();
                }
            }
        },
        computed: {
            audioPercent: function() {
                if (this.currentTime && this.totalTime) {
                    return parseInt(this.currentTime * 100 / this.totalTime);
                }
                return 0;
            },
            timeValue: function() {
                return this.secondToMinute(this.currentTime)
            },
            playRateValue: function() {
                return this.playRate.toFixed(1);
            }
        },
        mounted() {
            const query = uni.createSelectorQuery().in(this);
            query.select(".control-box").boundingClientRect();
            query.exec(res => {
                this.processWidth = res[0].width;
            })
        },
        destroyed() {
            this.destroyedAudioContext();
        },
        methods: {
            tapPDF() {
                this.$emit("action", {
                    type: 'pdf'
                })
            },
            createAudioContext(src) {
                this.audioContext = uni.createInnerAudioContext();
                this.audioContext.autoplay = true;
                this.audioContext.src = src;
                this.audioContext.playbackRate = this.playRate;
                this.audioContext.onCanplay((res) => {
                    this.onCanplayWatch(res);
                })
                this.audioContext.onPlay(res => {
                    this.onPlayWatch(res);
                })
                this.audioContext.onPause(res => {
                    this.onPauseWatch(res);
                })
                this.audioContext.onStop(res => {
                    this.onStopWatch(res);
                })
                this.audioContext.onEnded(res => {
                    this.onEndedWatch(res);
                })
                this.audioContext.onTimeUpdate(res => {
                    this.onTimeUpdateWatch(res);
                })
                this.audioContext.onWaiting(res => {
                    this.onWaitingWatch(res);
                })
            },
            destroyedAudioContext() {
                if (this.audioContext) {
                    this.audioContext.stop();
                    setTimeout(() => {
                        this.audioContext.offCanplay();
                        this.audioContext.offPlay();
                        this.audioContext.offPause();
                        this.audioContext.offStop();
                        this.audioContext.offEnded();
                        this.audioContext.offTimeUpdate();
                        this.audioContext.onWaiting();
                        this.audioContext.destroy();
                        this.audioContext = null;
                    }, 300)
                }
            },
            tapRate() {
                let itemList = [{
                        name: '0.5倍速',
                        value: 0.5
                    },
                    {
                        name: '0.8倍速',
                        value: 0.8
                    },
                    {
                        name: '1.0倍速',
                        value: 1
                    },
                    {
                        name: '1.2倍速',
                        value: 1.2
                    },
                    {
                        name: '1.5倍速',
                        value: 1.5
                    },
                    {
                        name: '2倍速',
                        value: 2
                    }
                ]
                uni.showActionSheet({
                    itemList: itemList.map(item => {
                        return item.name
                    }),
                    success: (res) => {
                        let rate = itemList[res.tapIndex].value;
                        this.playRate = rate;
                        this.audioContext.playbackRate = rate;
                    }
                })
            },
            tapPlay() {
                if (this.play) {
                    this.audioContext.pause();
                } else {
                    this.audioContext.play();
                }
            },
            controlChange(e) {
                if (e.detail.source == 'touch') {
                    let x = e.detail.x;
                    let percent = x / this.processWidth;
                    // 直接 seek 之后 onTimeUpdate 失效
                    // 需要先暂停，再跳转，延迟之后再播放，可以解决这个问题
                    this.audioContext.pause();
                    this.currentTime = this.totalTime * percent;
                    this.audioContext.seek(this.currentTime);
                    setTimeout(() => {
                        this.audioContext.play();
                    }, 500)
                }
            },
            changeControX() {
                let percent = 0;
                if (this.currentTime && this.totalTime) {
                    percent = this.currentTime / this.totalTime;
                }
                let x = this.processWidth * percent;
                this.controlX = `${x}px`
            },
            onCanplayWatch(res) {
                console.log("onCanplay");
            },
            onPlayWatch(res) {
                console.log("onPlay");
                this.play = true;
            },
            onPauseWatch(res) {
                console.log("onPause");
                this.play = false;
            },
            onStopWatch(res) {
                console.log("onStop");
                this.play = false;
            },
            onEndedWatch(res) {
                console.log("onEnded");
                this.play = false;
                this.currentTime = 0;
                this.changeControX();
            },
            onTimeUpdateWatch(res) {
                console.log("onTimeUpdate", this.audioContext.currentTime, this.audioContext.duration);
                this.totalTime = this.audioContext.duration;
                this.currentTime = this.audioContext.currentTime;
                this.changeControX();
            },
            onWaitingWatch(res) {
                console.log("onWaiting")
            },
            secondToMinute(second) {
                let result;
                let time = parseInt(second);
                let minuteValue = parseInt(time / 60);
                let secondValue = parseInt(time % 60);
                let zeroFill = function(value) {
                    if (value < 10) {
                        return `${0}${value}`
                    }
                    return value;
                }
                minuteValue = zeroFill(minuteValue);
                secondValue = zeroFill(secondValue);
                return `${minuteValue}:${secondValue}`
            }
        }
    }
</script>

<style lang="scss" scoped>
    .bar {
        background: #f1f1f7;
        height: 100%;
        border-radius: 15rpx;

        .item {
            margin: 0 15rpx;
            margin-right: 0;
        }

        .item:last-child {
            margin-right: 15rpx;
        }

        .progress {
            .body {
                width: 100%;
                height: 8px;
            }

            .control-box {
                width: 100%;
                height: 8px;

                .control-button {
                    height: 1rpx;
                    height: 8px;

                    .control-bg {
                        top: 50%;
                        left: 50%;
                        transform: translate(-50%, -50%);
                        height: 40rpx;
                        width: 20rpx;
                        background: #fff;
                        border-radius: 10rpx;
                    }
                }

                .control {}
            }
        }

        .time {
            font-size: 24rpx;
            color: #b1b2b3;
        }

        .button {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;

            width: 70rpx;
            height: 70rpx;
            border-radius: 50%;
            border: 4rpx solid #fff;
        }

        .play {
            border-color: #333;
            background: #ffda17;
        }

        .speed {
            border-color: #333;
            background: #ffda17;

            .title {
                font-weight: 700;
                font-size: 22rpx;
                color: #333;
            }

            .title::after {
                content: " x";
                font-size: 18rpx;
            }
        }

        .pdf {
            border-color: #333;
            background: #ffda17;
        }
    }
</style>